Completed
Push — master ( 8caa6f...c37a57 )
by Jan
20s queued 13s
created

frames-reader.ts ➔ decodeFrames   A

Complexity

Conditions 4

Size

Total Lines 24
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 24
rs 9.45
c 0
b 0
f 0
cc 4
1
import { Frame } from './Frame'
2
import { getFrameSize } from './FrameHeader'
3
import { Options } from "./types/Options"
4
import { Tags, TagIdentifiers } from './types/Tags'
5
import { convertRawTagsToTagAliases } from "./TagsConverters"
6
import { getFrameOptions } from './util-frame-options'
7
8
type FramesData = {
9
    buffer: Buffer
10
    version: number
11
}
12
13
export function getTags(
14
    framesData: FramesData | undefined,
15
    options: Options = {}
16
) {
17
    const { buffer, version } =
18
        framesData ?? { buffer: Buffer.alloc(0), version: 3 }
19
20
    const frames = decodeFrames(buffer, version, options)
21
    return convertFramesToTags(frames, version, options)
22
}
23
24
function convertFramesToTags(
25
    frames: Frame[],
26
    _version: number,
27
    options: Options = {}
28
): Tags | TagIdentifiers {
29
    const pushValue = (dest: unknown, value: unknown) => {
30
        const destArray = Array.isArray(dest) ? dest : []
31
        destArray.push(value)
32
        return destArray
33
    }
34
    const getValue = (_dest: unknown, value: unknown) => value
35
36
    const rawTags = frames.reduce<TagIdentifiers>((tags, frame) => {
37
        const frameId = frame.identifier as keyof TagIdentifiers
38
        const isMultiple = getFrameOptions(frameId).multiple
39
        const makeValue = isMultiple ? pushValue : getValue
40
        tags[frameId] = makeValue(tags[frameId], frame.getValue()) as never
41
        return tags
42
    }, {})
43
44
    if (options.onlyRaw) {
45
        return rawTags
46
    }
47
48
    const tags = convertRawTagsToTagAliases(rawTags)
49
    if (options.noRaw) {
50
        return tags
51
    }
52
    return { ...tags, raw: rawTags }
53
}
54
55
function decodeFrames(
56
    buffer: Buffer,
57
    version: number,
58
    options: Options = {}
59
): Frame[] {
60
    const frames = []
61
    while(buffer.length && buffer[0] !== 0x00) {
62
        const frameSize = getFrameSize(buffer, version)
63
64
        // Prevent errors due to broken data.
65
        if (frameSize > buffer.length) {
66
            break
67
        }
68
69
        const frameBuffer = buffer.subarray(0, frameSize)
70
        const frame = Frame.createFromBuffer(frameBuffer, version)
71
        if (frame && !isFrameDiscarded(frame.identifier, options)) {
72
            frames.push(frame)
73
        }
74
75
        buffer = buffer.subarray(frameSize)
76
    }
77
    return frames
78
}
79
80
function isFrameDiscarded(frameId: string, options: Options) {
81
    if (Array.isArray(options.exclude) && options.exclude.includes(frameId)) {
82
        return true
83
    }
84
    return Array.isArray(options.include) && !options.include.includes(frameId)
85
}
86